Skip to content

Render ini config files from an ordered list, and collapse the two ini renderers into one - #945

Open
khusmann wants to merge 6 commits into
mainfrom
ordered-config-library
Open

khusmann wants to merge 6 commits into
mainfrom
ordered-config-library

Conversation

@khusmann

@khusmann khusmann commented Sep 25, 2026 •

Copy link
Copy Markdown

Part 1 of 2 for #944.

rstudio-library's ini helpers rendered a config file from a map, and Go templates iterate maps in sorted key order. For files whose behavior depends on the order of their sections or entries — /etc/rstudio/profiles, launcher.*.profiles.conf, launcher.*.resources.conf, repos.conf — that silently changes what the file does, and nothing in values.yaml shows it.

Part 2 (#953) bumps rstudio-workbench onto this, adds the deprecation warning, and updates the docs. It has to wait until rstudio-library 0.1.38 is published, since consumers resolve the library from helm.rstudio.com rather than the working tree.

The ordered form

A file's contents may now be a list, rendered in the order written:

config:
  server:
    profiles:
      - "*":
          max-memory-mb: 1024
      - "@analysts":
          max-memory-mb: 4096
  session:
    repos.conf:
      - Internal: https://pkgs.example.com/internal
      - CRAN: https://packagemanager.posit.co/cran/latest

Previously a list rendered broken lines like *=map[max-memory-mb:1024], with no section headers at all.

Each entry holds exactly one key. That key names a [section] when its value is a map, and an entry when it is not. An entry with more than one key, or none, is rejected — the shapes those produced were all unusable, and the error names the keys and shows where the - goes.

A value is a single value, or a list of them. A list is comma-joined, which is how these files express several values for one option: /etc/rstudio/profiles has cpu-affinity and the AI provider allow/deny lists, launcher.*.profiles.conf has resource-profiles. A map has no representation — ini files have no nesting — and neither does a list holding maps or lists; both fail.

At a file's top level, a list of maps still means several sections with the same name (launcher.conf's cluster:), unchanged.

A raw string is still passed through verbatim.

Collapsing the two ini renderers

profiles.ini was a fork of config.ini that added comma-joining and the job-json-overrides encoding. That split meant the same YAML rendered differently depending on which file it was in — a list as an option's value comma-joined under config.profiles and was rejected under config.server.

Both behaviors moved where they belong:

  • Comma-joining is in config.ini, at every depth, as above. It is a property of these file formats, not of one file.
  • The job-json-overrides encoding moved out of the renderer into apply-everyone-and-default-to-others, which already rewrote those entries to add their file key. It is a chart-level idea, not an ini one, so the renderer now only ever sees single values.

With both in place, profiles.ini.singleFile, the old multi-file profiles.ini, and collapse-array are removed, and profiles files render through config.ini like every other ini file.

Breaking

  • rstudio-library.profiles.ini.advanced is renamed to rstudio-library.profiles.ini — it is the only profiles helper now, so "advanced" meant nothing. Consumers update their include when they adopt 0.1.38. rstudio-connect pins 0.1.36 and is unaffected until it bumps; if missed, the failure is loud (no template … associated), not silent.
  • apply-everyone-and-default-to-others takes a file key and renders the whole file, rather than its caller emitting the name: | header.
  • A list of values no longer produces repeated keys at a file's top level; it is comma-joined. No chart default, lint/, or ci/ file in this repo uses that shape, and rserver.conf's option schema has no list-typed options. chronicle-local.gcfg is the one format that genuinely supports repeated keys, but it cannot express them through this renderer today either — see chronicle-local.gcfg is rendered as ini, and its values are never quoted #954.
  • A map as an option's value now fails rather than rendering key=map[a:1]. Confirmed harmless for Chronicle, whose config struct has no map[...] field and therefore no gcfg subsections.

Testing

other-charts/rstudio-library-test covers, for config.ini and the profiles helpers:

  • the list form for each order-sensitive file — sections and entries in order, with headers where the file has them
  • the map form — sorted by name, as before
  • the raw string form — verbatim
  • comma-joining, at both depths
  • repeated section names (launcher.conf's cluster:)
  • job-json-overrides merging and the JSON payloads it generates
  • every rejected shape: multi-key entry, empty entry, non-map entry, map as a value, list holding a map

94 tests pass. Rendering every values file under charts/*/lint/ and charts/*/ci/ is unchanged except where a previously-broken shape now renders correctly.

@khusmann
khusmann requested review from a team as code owners September 25, 2026 00:50
@khusmann khusmann changed the title Render order-sensitive ini config files from an ordered list Render ini config files from an ordered list, and collapse the two ini renderers into one Sep 30, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant